package com.hnust.root.common.util;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.hnust.root.common.constant.GlobalConstant;
import com.hnust.root.web.config.GlobalConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PreDestroy;
import java.io.*;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;

/**
 * @Author zhusir
 * @Date 2018/12/8
 * @Desc oss服务相关工具类
 */
@Component
public class OSSUtil {
    private static final Log LOGGER = LogFactory.get();

    @Value("${oss.accessKeyId}")
    private String accessKeyId;

    @Value("${oss.accessKeySecret}")
    private String accessKeySecret;

    private static String endpoint = GlobalConfig.getEndPoint();

    private OSSClient ossClient;

    /**
     * 异步上传文件到OSS
     *
     * @param filename OSS上存放的文件名
     * @param file     要上传的文件
     * @throws IOException
     */
    @Async
    public CompletableFuture<Boolean> putObjectAsyn(String filename, MultipartFile file) throws IOException, OSSException, ClientException {

        LOGGER.info("开始上传文件：{},文件大小为：{} B", file.getOriginalFilename(), file.getSize());
        long start = System.currentTimeMillis();
        PutObjectResult result = null;
        OSSClient ossClient = getOssClient();

        try (InputStream inputStream = file.getInputStream();
             BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
            result = ossClient.putObject(GlobalConfig.getBucketName(), filename, bufferedInputStream);
        } catch (FileNotFoundException e) {
            LOGGER.error("文件不存在" + e.getMessage());
        }
        LOGGER.info("文件：{} 上传完毕，耗时：{} ms", file.getOriginalFilename(), System.currentTimeMillis() - start);
        return CompletableFuture.completedFuture(null != result);
    }

    public CompletableFuture<Boolean> getObject(String fileUrl, String localFileName) throws OSSException, ClientException {
        boolean result = true;
        OSSClient ossClient = getOssClient();
        try {
            String ossUrl = GlobalConfig.getOssDomain();
            String objectName = fileUrl.replace(ossUrl, "");
            // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
            LOGGER.info("开始下载文件，原件存储位置：{}", fileUrl);
            long startTime = System.currentTimeMillis();
            ossClient.getObject(new GetObjectRequest(GlobalConfig.getBucketName(), objectName), new File(localFileName));
            LOGGER.info("文件下载完毕，耗时 {} ms", System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            result = false;
            LOGGER.info("文件下载异常");
        }
        return CompletableFuture.completedFuture(result);
    }

    /**
     * 延迟初始化ossclient
     * @return
     */
    private OSSClient getOssClient() {
        if (ossClient == null) {
            synchronized (OSSClient.class) {
                if (ossClient == null) {
                    ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
                }
            }
        }
        return ossClient;
    }

    /**
     * 销毁oss client.
     */
    @PreDestroy
    private void destroyOssClient() {
        if (null != ossClient) {
            ossClient.shutdown();
        }
    }
}
